<?php
/**
 * Created by PhpStorm.
 * User: gyq
 * Date: 2018/11/13
 * Time: 20:46
 */

namespace app\api\service;


use app\api\model\OrderProduct;
use app\api\model\Product;
use app\api\model\UserAddress;
use app\lib\exception\OrderException;
use app\lib\exception\UserException;
use app\api\model\Order as OrderModel;
use think\Db;
use think\Exception;

class Order
{
//  订单products  客户端传过来的products
    protected $oProducts;
//   真实的商品信息，包括库存量
    protected $products;

    protected $uid;

    public function __construct()
    {

    }

    public function place($uid, $oProducts)
    {
        $this->oProducts = $oProducts;
        $this->products = $this->getProductsByOrder($oProducts);
        $this->uid = $uid;

        $status = $this->getOrderStatus();
        if (!$status['pass']) {
            $status['order_id'] = -1;
            return $status;
        }
//        创建订单
//        快照订单
        $orderSnap = $this->SnapOrder($status);
        $order = $this->createOrder($orderSnap);
        $order['pass'] = true;
        return $order;
    }

    private function createOrder($orderSnap)
    {
        Db::startTrans();
        try {
            $orderNum = self::makeOrderNum();
            $order = new OrderModel();
            $order->order_no = $orderNum;
            $order->user_id = $this->uid;
            $order->total_price = $orderSnap['orderPrice'];
            $order->snap_img = $orderSnap['snapImg'];
            $order->snap_name = $orderSnap['snapName'];
            $order->total_count = $orderSnap['totalCount'];
            $order->snap_items = json_encode($orderSnap['pStatus']);
            $order->snap_address = json_encode(UserAddress::where('user_id', 'eq', $this->uid)->find()->toArray());
            $order->save();

            $orderId = $order->id;
            $createTime = $order->create_time;
            foreach ($this->oProducts as &$p) {
                $p['order_id'] = $orderId;
            }
            $orderProduct = new OrderProduct();
            $orderProduct->saveAll($this->oProducts);
            Db::commit();
            return [
                'order_no' => $orderNum,
                'order_id' => $orderId,
                'create_time' => $createTime
            ];
        } catch (Exception $ex) {
            Db::rollback();
            throw $ex;
        }
    }

    public static function makeOrderNum()
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn = $yCode[intval(date('Y') - 2018)] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
        return $orderSn;
    }

    private function snapOrder($status)
    {
        $orderSnap = [
            'orderPrice' => 0,
            'totalCount' => 0,
            'pStatus' => [],
            'snapAddress' => null,
            'snapName' => '',
            'snapImg' => ''
        ];
        $orderSnap['orderPrice'] = $status['orderPrice'];
        $orderSnap['totalCount'] = $status['orderCount'];
        $orderSnap['pStatus'] = $status['pStatusArray'];
        $orderSnap['snapAddress'] = json_encode($this->getUserAddress());
        $orderSnap['snapName'] = $this->products[0]['name'];
        if (count($this->products) > 1) {
            $orderSnap['snapName'] .= '等';
        }
        $orderSnap['snapImg'] = $this->products[0]['main_img_url'];
        return $orderSnap;
    }

    private function getUserAddress()
    {
        $user = UserAddress::where('user_id', 'eq', $this->uid)->find();
        if (!$user) {
            throw new UserException([
                'msg' => '用户地址不存在，下单失败',
                'errorcode' => 60001
            ]);
        }
        return $user->toArray();
    }

    private function getOrderStatus()
    {
        $status = [
            'pass' => true,
            'orderPrice' => 0,
            'orderCount' => 0,
            'pStatusArray' => []
        ];
        foreach ($this->oProducts as $oProduct) {
            $pStatus = $this->getProductStatus($oProduct['product_id'], $oProduct['count'], $this->products);
            if (!$pStatus['haveStock']) {
                $status['pass'] = false;
            }
            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['orderCount'] += $pStatus['count'];
            array_push($status['pStatusArray'], $pStatus);
        }
        return $status;
    }

//    检测商品库存
    public function checkOrderStock($orderID)
    {
        $oProducts = OrderProduct::where('order_id', 'eq', $orderID)->select();
        $this->oProducts = $oProducts;
        $this->products = $this->getProductsByOrder($oProducts);
        $status = $this->getOrderStatus();
        return $status;
    }

//    获取商品的状态
    private function getProductStatus($oPid, $oCount, $products)
    {
        $pIndex = -1;
        $pStatus = [
            'id' => null,
            'haveStock' => false,
            'count' => 0,
            'name' => '',
            'totalPrice' => 0
        ];
        for ($i = 0; $i < count($products); $i++) {
            if ($oPid == $products[$i]['id']) {
                $pIndex = $i;
            }
        }
        if ($pIndex == -1) {
            throw new OrderException([
                'msg' => 'id为' . $oPid . '的商品不存在，创建订单失败'
            ]);
        } else {
            $product = $products[$pIndex];
            $pStatus['id'] = $product['id'];
            $pStatus['count'] = $oCount;
            $pStatus['name'] = $product['name'];
            $pStatus['totalPrice'] = $product['price'] * $oCount;
            if ($product['stock'] >= $oCount) {
                $pStatus['haveStock'] = true;
            }
        }
        return $pStatus;
    }

//    根据订单信息查找真实商品信息
    private function getProductsByOrder($oProducts)
    {
        $oPids = [];
        foreach ($oProducts as $item) {
            $oPids[] = $item['product_id'];
        }
        $products = Product::all($oPids)->visible(['id', 'name', 'price', 'stock', 'main_img_url'])->toArray();
        return $products;
    }

}